package de.bht.mi.kriz.multitouch.components;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Paint.Style;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.RelativeLayout;

public class MultiTouchViewElement extends RelativeLayout {

	protected Point localPosition = new Point(0,0);
	protected Point globalPosition = new Point(0,0);
	private int alpha = 255;
	
	public Point getGlobalPosition() {
		return globalPosition;
	}

	protected String title = "";
	protected int drawColor = 0xffcccccc;
	
	protected float width = 0.0f;
	protected float height = 0.0f;
	
	public int TITLE_SPACE = 0;
	public int MIN_SIZE = 0;
	
	public final static int MOVE_HANDLE = 100;
	public final static int NONE = 0;
	
	public final static int GRAB_TOLLERANCE = 5;
	
	public String getTitle() {
		return title;
	}
	
	public void setWidth(float w) {
		width = w;
	}
	
	public void setHeight(float h) {
		height = h;
	}
	
	//calculates world coordinates to view coordinates and moves / resizes view
	public void setBottomLeftCorner(int x, int y)
	{
		int xDiff = x - globalPosition.x;
		int yDiff = (int) (y - (globalPosition.y+height));
		
		globalPosition.x += xDiff;
		refreshPositions();

		width 	-= xDiff;
		height 	+= yDiff;
		
		refreshBounds();	
	}

	//calculates world coordinates to view coordinates and moves / resizes view
	public void setBottomRightCorner(int x, int y)
	{
		int xDiff = (int) (x - (globalPosition.x+width));
		int yDiff = (int) (y - (globalPosition.y+height));
		
		width 	+= xDiff;
		height 	+= yDiff;
		
		refreshBounds();	
	}

	private void refreshBounds() {
		if(height <= MIN_SIZE)
		{
			height = MIN_SIZE;
		}
		if(width <= MIN_SIZE)
		{
			width = MIN_SIZE;
		}
		if(globalPosition.y>getHeight()-height-TITLE_SPACE)
		{
			height = (getHeight()-globalPosition.y-TITLE_SPACE);
		}
	}

	public void setTitle(String title) {
		this.title = title;
	}

	
	public Point getPosition() {
		return localPosition;
	}
	

	private void refreshChildren() 
	{
		for(int i=0; i<getChildCount(); i++)
		{
			if(getChildAt(i) instanceof MultiTouchViewElement)
			{
				MultiTouchViewElement element = (MultiTouchViewElement)getChildAt(i);
				element.refreshPositions();
			}
		}
	}
	
	@Override
	public void addView(View child) {
		// TODO Auto-generated method stub
		super.addView(child);
		
		if(child instanceof MultiTouchViewElement)
		{
			MultiTouchViewElement mtveChild = (MultiTouchViewElement)child;
			mtveChild.refreshPositions();
		}
	}
	
	public void refreshPositions()
	{
		setLocalPosition(this.localPosition);
	}	
	
	public void setLocalPosition(Point position)
	{
		Point globalPositionOfParent = getAbsolutePosition(this.getParent());
		
		this.localPosition = position;
		this.globalPosition.set(position.x + globalPositionOfParent.x, position.y + globalPositionOfParent.y);
		refreshChildren();
	}
	
	public void setGlobalPosition(Point position)
	{
		Point globalPositionOfParent = getAbsolutePosition(this.getParent());
		
		Log.d("func_setGlobalPosition", "set to: "+position);
		
		this.globalPosition = position;
		
		//check for global bounds
		if(globalPosition.x<0)
		{
			globalPosition.x=0;
		}
		else if(globalPosition.x>this.getWidth()-width)
		{
			globalPosition.x=(int) (getWidth()-width);
		}
		
		if(globalPosition.y<0)
		{
			globalPosition.y=0;
		}
		else if(globalPosition.y>getHeight()-height-TITLE_SPACE)
		{
			globalPosition.y=(int) (getHeight()-height-TITLE_SPACE);
		}
		
		this.localPosition.set(globalPosition.x - globalPositionOfParent.x, globalPosition.y - globalPositionOfParent.y);
		refreshChildren();
	}

	public void setPosition(Point position) 
	{
		Point globalPosition = getAbsolutePosition();
		Point globalPositionOfParent = getAbsolutePosition(this.getParent());

		Log.d("func_setPosition", "set to: "+position+" global@: "+globalPosition+" globalPositionOfParent@: "+globalPositionOfParent);
		
		//check for global bounds
		if(globalPositionOfParent.x+position.x<0)
		{
			position.x=0-globalPositionOfParent.x;
		}
		else if(globalPositionOfParent.x+position.x>this.getWidth()-width)
		{
			position.x=(int) (getWidth()-width)-globalPositionOfParent.x;
		}
		
		if(globalPositionOfParent.y+position.y<0)
		{
			position.y=0-globalPositionOfParent.y;
		}

		else if(globalPositionOfParent.y+position.y>getHeight()-height-TITLE_SPACE)
		{
			position.y=(int) (getHeight()-height-TITLE_SPACE)-globalPositionOfParent.y;
		}	
		
		setLocalPosition(position);
	}


	public void setPosition(int x, int y) 
	{
		setPosition(new Point(x,y));
	}

	public MultiTouchViewElement(Context context) {
		super(context);
		initializeElement(context);
	}

	protected void initializeElement(Context context) {
		//ensure ViewGroup will be drawn
		setWillNotDraw(false);
		addView(new View(context));
	}
	
	/**
	 * 
	 * @param context
	 * @param p position
	 */
	public MultiTouchViewElement(Context context, Point p) {
		super(context);
		initializeElement(context);
		
		setLocalPosition(p);
	}
	
	/**
	 * 
	 * @param context
	 * @param x x-Position
	 * @param y y-Position
	 */
	public MultiTouchViewElement(Context context, int x, int y) {
		super(context);
		initializeElement(context);
		
		setLocalPosition(new Point(x,y));
	}	
	
	@Override
	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);
		
		float strokeWidth = 3f;
		
		Paint pathPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
		pathPaint.setStyle(Style.STROKE);
		pathPaint.setStrokeWidth(strokeWidth);
		pathPaint.setColor(this.drawColor);
		pathPaint.setAlpha(getAlpha());
		
		Path pth = new Path();
		pth.moveTo(0, 0);
		pth.lineTo(0, getHeight());
		pth.lineTo(getWidth(), getHeight());
		pth.lineTo(getWidth(), 0);
		pth.close();
		
		canvas.drawPath(pth, pathPaint);		
		
	}
	
	//checks which view-component-part is at the world coordinate located point
	public int check(float x, float y) 
	{
		return NONE;
	}
	
	//static helper method to move a View from one ViewGroup to another
	public static void moveView(int index, ViewGroup source, ViewGroup destination) 
	{
		
		View element = source.getChildAt(index);
		source.removeViewAt(index);
		destination.addView(element);
	}
	
	public static Point getAbsolutePosition(View view, Point relativePosition)
	{
		Point position = new Point(relativePosition);
		Log.d("func_getAbsolutePosition", "relative: "+position.toString());
		
		ViewParent vp = view.getParent();
		if(vp instanceof MultiTouchViewElement)
		{
			MultiTouchViewElement v = (MultiTouchViewElement)vp;
			
			position.x += v.localPosition.x;
			position.y += v.localPosition.y;
			
			return getAbsolutePosition(v, position);
		}
		return position;
	}
	
	
	private Point getAbsolutePosition(ViewParent parent) {
		return getAbsolutePosition((View)parent);
	}	
	
	public static Point getAbsolutePosition(View view)
	{
		//this view is evaluable
		if(view instanceof MultiTouchViewElement)
		{
			MultiTouchViewElement v = (MultiTouchViewElement)view;
			Point position = new Point(v.localPosition);
			ViewParent vp = v.getParent();
			
			Log.d("func_getAbsolutePosition", "relative: "+position.toString());
			
			//this view has evaluable parent
			if(vp instanceof MultiTouchViewElement)
			{
				MultiTouchViewElement v2 = (MultiTouchViewElement)vp;
				
				position.x += v2.localPosition.x;
				position.y += v2.localPosition.y;
				
				return getAbsolutePosition(v2, position);
			}
			return position;
		}
		else
		{
			return new Point(0,0);
		}
	}	
	
	public Point getAbsolutePosition()
	{
		Point position = new Point(this.localPosition);
		ViewParent vp = this.getParent();
		
		Log.d("func_getAbsolutePosition", "relative: "+position.toString());
		
		//this view has evaluable parent
		if(vp instanceof MultiTouchViewElement)
		{
			MultiTouchViewElement v = (MultiTouchViewElement)vp;
			
			position.x += v.localPosition.x;
			position.y += v.localPosition.y;
			
			return getAbsolutePosition(v, position);
		}
		return position;
	}

	public int getAlpha() {
		return alpha;
	}

	public void setAlpha(int alpha) {
		this.alpha = alpha;
	}	
}